package com.pandora.component;

import java.io.File;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.jdom2.Document;
import org.jdom2.Element;

import com.pandora.exception.UtilException;
import com.pandora.util.ClassUtil;
import com.pandora.util.DomainUtil;
import com.pandora.util.FileUtil;
import com.pandora.util.PropertyUtil;
import com.pandora.util.StringUtil;
import com.pandora.util.XmlUtil;

public class ApplicationContext {
	public static ThreadLocal<HttpSession> sessionThreadLocal=new ThreadLocal<HttpSession>();
	public static ThreadLocal<HttpServletRequest> requestThreadLocal=new ThreadLocal<HttpServletRequest>();
	public static ThreadLocal<HttpServletResponse> responseThreadLocal=new ThreadLocal<HttpServletResponse>();
	public static Map<String, String> propertyConfigs=new HashMap<String, String>();
	public static Map<String, Object> xmlConfigs=new HashMap<String, Object>() ;
	public static Map<String, String> htmlPaths=new HashMap<String, String>();
	
	public void init() throws UtilException {
		parseProp();
		parseXml();
	}
	
	public static void threadBinding(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) {
		HttpSession httpSession=httpServletRequest.getSession();
		sessionThreadLocal.set(httpSession);
		requestThreadLocal.set(httpServletRequest);
		responseThreadLocal.set(httpServletResponse);
	}
	
	public static HttpSession getHttpSession() {
		return sessionThreadLocal.get();
	}
	public static HttpServletRequest getHttpServletRequest() {
		return requestThreadLocal.get();
	}
	public static HttpServletResponse getHttpServletResponse() {
		return responseThreadLocal.get();
	}
	
	
	private static final String XML_RESOURCE_PATH = "classpath:xml/systemConfig.xml";
	private static final String PROP_RESOURCE_PATH="classpath:properties";
	
	protected static final String CLASSALIAS = "classAlias";// 类标签名
	protected static final String PROPERTY = "property";// 属性标签名
	protected static final String CONFIG = "config";//配置标签名
	protected static final String CLASS_NAME = "name";//类别名
	protected static final String CONFIG_NAME = "name";//配置名称
	protected static final String CONFIG_CLASSNAME = "class";//配置引用类别名
	protected static final String PROPERTY_NAME = "name";//属性名称

	
	private void parseProp() throws UtilException {
		ApplicationContext.propertyConfigs=PropertyUtil.getProps(PROP_RESOURCE_PATH);
	}

	public void parseXml() throws UtilException {
		InputStream in=FileUtil.getResourcAsStream(XML_RESOURCE_PATH);
		//不保存
		File no_save_file=null;
		XmlUtil.domXml(in,no_save_file,new DomHandler() {
			Map<String, String> classAliasesMap = new HashMap<String, String>();// 初始化别名列表
			@Override
			public void resultCallback(Document doc) throws UtilException {
				Element root = doc.getRootElement();
				// 读取 类初始化方案（需要初始化的ClassName）
				List<Element> classAliases = root.getChildren(CLASSALIAS);
				for (Element classAlias : classAliases) {
					String name = classAlias.getAttributeValue(CLASS_NAME);
					String className = classAlias.getText();
					if (StringUtil.isNotBlank(name)
							&& StringUtil.isNotBlank(className)) {
						classAliasesMap.put(name, className);
					}
				}
				// 读取各配置 并初始化为类对象存储到内存中
				List<Element> configs = root.getChildren(CONFIG);
				for (Element config : configs) {
					String aliase = config.getAttributeValue(CONFIG_CLASSNAME);
						// 根据别名拿到ClassName
						String className = classAliasesMap.get(aliase);
						if (StringUtil.isBlank(className)) {
							throw new UtilException("xml中没检索到关于类：" + aliase
									+ "的配置");
						}
						Object obj =ClassUtil.newInstance(className);

						// 为字段注入值(值来源为Config标签下的property标签)
						List<Element> properties = config.getChildren(PROPERTY);
						for (Element property : properties) {
							String propertyName = property
									.getAttributeValue(PROPERTY_NAME);
							String propertyValue = property.getText().trim();
							DomainUtil.setDeclaredFieldValue(obj, propertyName, propertyValue);
						}	
						//将配置添加到map 键为：config的name属性
						String name = config.getAttributeValue(CONFIG_NAME);
						ApplicationContext.xmlConfigs.put(name, obj);

				}
			}
		});
	}
	
	
	
	@SuppressWarnings("unchecked")
	public static <T>T getSystemConfig(String configName) {
		Object object=ApplicationContext.xmlConfigs.get(configName);
		return (T)object;
	}
	public static String getProperty(String propName) {
		return propertyConfigs.get(propName);
	}
	
	
	
}
